/*
 * @(#)WsAction.java
 * 2012-6-28 下午02:10:38
 * 
 *
 * Copyright (c) 2018-2028, HangZhou QiYun InfoTech Co.,Ltd. .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qyxx.platform.ws.web;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.struts2.convention.annotation.Namespace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;

import com.qyxx.platform.common.json.JsonOutput;
import com.qyxx.platform.common.module.web.CrudActionSupport;
import com.qyxx.platform.common.module.web.FormatMessage;
import com.qyxx.platform.common.module.web.Messages;
import com.qyxx.platform.common.utils.spring.SpringContextHolder;
import com.qyxx.platform.common.utils.web.struts2.Struts2Utils;
import com.qyxx.platform.gsc.GsParseUtils;
import com.qyxx.platform.gsc.utils.SystemParam;
import com.qyxx.platform.sysmng.accountmng.entity.User;
import com.qyxx.platform.sysmng.accountmng.service.AccountManager;
import com.qyxx.platform.sysmng.exception.GsException;
import com.qyxx.platform.sysmng.upgrade.entity.Upgrade;
import com.qyxx.platform.sysmng.upgrade.service.UpgradeManager;
import com.qyxx.platform.sysmng.utils.Constants;


/**
 *  设计器接口服务类
 *  
 *  @author gxj
 *  @version 1.0 2012-6-28 下午02:10:38
 *  @since jdk1.6
 */
@Namespace("/ws")
public class WsAction extends CrudActionSupport<Object> {

	private static final long serialVersionUID = -2486108495132432927L;
	
	private static SystemParam sp = SpringContextHolder.getBean("systemParam");
	
	private File configFile;
	
	private AccountManager accountManager;
	
	private Md5PasswordEncoder md5 = new Md5PasswordEncoder();
	
	private String loginName;
	
	private String passwd;
	
	private String file;
	
	private UpgradeManager upgradeManager;
	
	private User user;
	
	private Boolean isFullUpdate = false;//是否全量更新

	/**
	 * @return user
	 */
	public User getUser() {
		return user;
	}

	
	/**
	 * @param user
	 */
	public void setUser(User user) {
		this.user = user;
	}

	/**
	 * @return accountManager
	 */
	public AccountManager getAccountManager() {
		return accountManager;
	}
	
	/**
	 * @param accountManager
	 */
	@Autowired
	public void setAccountManager(AccountManager accountManager) {
		this.accountManager = accountManager;
	}
	
	/**
	 * @return upgradeManager
	 */
	public UpgradeManager getUpgradeManager() {
		return upgradeManager;
	}

	
	/**
	 * @param upgradeManager
	 */
	@Autowired
	public void setUpgradeManager(UpgradeManager upgradeManager) {
		this.upgradeManager = upgradeManager;
	}

	/**
	 * @return loginName
	 */
	public String getLoginName() {
		return loginName;
	}

	/**
	 * @param loginName
	 */
	public void setLoginName(String loginName) {
		this.loginName = loginName;
	}

	
	/**
	 * @return passwd
	 */
	public String getPasswd() {
		return passwd;
	}

	
	/**
	 * @param passwd
	 */
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}

	/**
	 * @return configFile
	 */
	public File getConfigFile() {
		return configFile;
	}

	
	/**
	 * @param configFile
	 */
	public void setConfigFile(File configFile) {
		this.configFile = configFile;
	}
	
	

	
	/**
	 * @return file
	 */
	public String getFile() {
		return file;
	}

	
	/**
	 * @param file
	 */
	public void setFile(String file) {
		this.file = file;
	}
	
	

	
	/**
	 * @return isFullUpdate
	 */
	public Boolean getIsFullUpdate() {
		return isFullUpdate;
	}


	
	/**
	 * @param isFullUpdate
	 */
	public void setIsFullUpdate(Boolean isFullUpdate) {
		this.isFullUpdate = isFullUpdate;
	}


	@Override
	public String list() throws Exception {
		return SUCCESS;
	}

	@Override
	public String input() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 接口上传config包，进行远程部署
	 * @see com.qyxx.platform.common.module.web.CrudActionSupport#save()
	 */
	@JsonOutput
	@Override
	public String save() throws Exception {
		if(checkAuth()) {
			String jwpPathName = DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMddHHmmssSSS");
			boolean vFlag = GsParseUtils.checkJwpVersion(jwpPathName, configFile, configFile.getName());
			if(vFlag) {
				upgradeJwp(jwpPathName, null, isFullUpdate);
			} else {
				//版本号不一致，需要提示
				FormatMessage fm = new FormatMessage();
				fm.setFlag(Messages.FAIL);
				fm.setMsg(jwpPathName);
				formatMessage.setMsg(fm);
			}
		}
		Struts2Utils.renderJson(formatMessage);
		return null;
	}
	
	/**
	 * 升级jwp
	 * 
	 * @param jwpPathName
	 * @param rollbackId 不为null表示重新部署
	 */
	private void upgradeJwp(String jwpPathName, Long rollbackId, Boolean isFullUpdate) {
		Upgrade upgradeLog = new Upgrade();
		upgradeLog.setDeployType(Upgrade.DEPLOY_TYPE_DS);
		upgradeLog.setLoginName(user.getLoginName());
		upgradeLog.setOrgName(user.getOrganizationName());
		upgradeLog.setRealName(user.getRealName());
		HttpServletRequest request = Struts2Utils.getRequest();
		upgradeLog.setIp(request.getRemoteAddr());
		upgradeLog.setMachineName(request.getRemoteHost());
		upgradeLog.setDeployUrl(jwpPathName);
		
		Date startDate = new Date();
		upgradeLog.setDeployTimeStart(startDate);
		try {
			if(null != rollbackId) {
				upgradeLog.setRollbackId(rollbackId);
			}
			String jwp = GsParseUtils.handleGs(jwpPathName, isFullUpdate);
			upgradeLog.setDeployName(jwp+(isFullUpdate?"【全量更新】":"【增量更新】"));
			upgradeLog.setDeployFlag(Upgrade.DEPLOY_FLAG_SUCCESS);
			formatMessage.setMsg(true);
		} catch(Exception e) {
			logger.error("部署jwp出现异常", e);
			String info = GsParseUtils.getStackTrace(e);
			formatMessage.setFlag(Messages.ERROR);
			formatMessage.setMsg(info);
			upgradeLog.setDeployName((isFullUpdate?"【全量更新】":"【增量更新】"));
			upgradeLog.setDeployFlag(Upgrade.DEPLOY_FLAG_FAIL);
			upgradeLog.setExceptionLog(info);
		}
		Date endDate = new Date();
		upgradeLog.setDeployTimeEnd(endDate);
		upgradeManager.saveUpgradeLog(upgradeLog);
	}
	
	/**
	 * 强制升级
	 * 
	 * @return
	 * @throws Exception
	 */
	@JsonOutput
	public String forceUpgrade() throws Exception {
		if(checkAuth()) {
			upgradeJwp(file, null, isFullUpdate);
		}
		Struts2Utils.renderJson(formatMessage);
		return null;
	}
	
	/**
	 * 检查用户权限
	 */
	private boolean checkAuth() {
		User user = accountManager.findUserByLoginName(loginName);
		if (user == null) {
			formatMessage.setFlag(Messages.ERROR);
			formatMessage.setMsg("用户" + loginName + " 不存在");
		} else {
			this.user = user;
			if(Constants.DISABLED.equals(user.getStatus())) {
				formatMessage.setFlag(Messages.ERROR);
				formatMessage.setMsg("用户" + loginName + "已经被禁用");
			} else {
				if(!Constants.IS_SUPER_USERR.equals(user.getIsSuperAdmin())) {
					formatMessage.setFlag(Messages.ERROR);
					formatMessage.setMsg("用户" + loginName + "不是超级管理员，没有权限操作");
				} else {
					String encodePass = md5.encodePassword(passwd, loginName);
					if(!user.getPassword().equals(encodePass)) {
						formatMessage.setFlag(Messages.ERROR);
						formatMessage.setMsg("密码输入不正确");
					}
				}
			}
		}
		return Messages.SUCCESS.equals(formatMessage.getFlag());
	}

	/**
	 * 接口登录，返回config包地址
	 * @see com.qyxx.platform.common.module.web.CrudActionSupport#view()
	 */
	@JsonOutput
	@Override
	public String view() throws Exception {
		if(checkAuth()) {
			try {
				String fileName = GsParseUtils.zipGsFile(com.qyxx.platform.gsc.utils.Constants.DEFAULT_CONFIG_FILE_NAME);
				formatMessage.setMsg(fileName);
			} catch(Exception e) {
				formatMessage.setFlag(Messages.ERROR);
				formatMessage.setMsg(GsParseUtils.getStackTrace(e));
			}
		}
		Struts2Utils.renderJson(formatMessage);
		return null;
	}
	
	/**
	 * 获取config文件，输出文件流
	 * 
	 * @return
	 * @throws Exception
	 */
	public String getConfig() throws Exception {
		boolean isInline = false;
		String filePath = sp.getUploadFilePath() + com.qyxx.platform.gsc.utils.Constants.GS_PACKAGE_PATH + file;
		writeFile(file, filePath, isInline);
		return null;
	}
	
	/**
	 * 获取version文件
	 * 
	 * @return
	 * @throws Exception
	 */
	public String getVersion() throws Exception {
		boolean isInline = false;
		String filePath = sp.getUploadFilePath() + com.qyxx.platform.gsc.utils.Constants.GS_PACKAGE_PATH
							+ com.qyxx.platform.gsc.utils.Constants.DEFAULT_VERSION_FILE_PATH;
		writeFile(com.qyxx.platform.gsc.utils.Constants.VERSION_FILE_NAME, filePath, isInline);
		return null;
	}
	
	/**
	 * 输出文件流方法
	 * 
	 * @param filePath
	 * @param isInline
	 * @throws Exception
	 */
	private void writeFile(String fileName, String filePath, boolean isInline) throws Exception {
		File fl = new File(filePath);
		if(!fl.exists()) {
			throw new GsException(filePath + "文件不存在");
		}
		String downFileName = new String(fileName.getBytes("utf-8"), "ISO8859-1");
        String inlineType = isInline ? "inline" : "attachment"; //  是否内联附件
        HttpServletResponse response = Struts2Utils.getResponse();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", inlineType+";filename=\""+downFileName+"\"");//客户看到的下载文件名  
        response.setContentLength((int) fl.length()); //  设置下载内容大小
        byte[] buffer = new byte[4096]; //  缓冲区 
        BufferedOutputStream output = null;     
        BufferedInputStream input = null;     
        try {     
            output = new BufferedOutputStream(response.getOutputStream());     
            input = new BufferedInputStream(new FileInputStream(fl));     
            int n = (-1);     
            while ((n = input.read(buffer, 0, 4096)) > -1) {     
                output.write(buffer, 0, n);     
            }     
            response.flushBuffer();
        } catch (Exception e) {     
        	//  用户可能取消了下载      
        } finally {     
            if (input != null)     
                input.close();     
            if (output != null)     
                output.close();     
        } 
	}
	

	@Override
	public String delete() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void prepareModel() throws Exception {
		// TODO Auto-generated method stub
		
	}

}
